<template>
    <div class="editor-container">
        <textarea ref="textarea"></textarea>
    </div>
</template>

<script>
import CodeMirror from "codemirror";
import "codemirror/lib/codemirror.css";
import "codemirror/mode/markdown/markdown.js";
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/css/css';
import 'codemirror/mode/htmlmixed/htmlmixed'; // HTML + JS + CSS 混合模式

// 代码错误检查
// eslint-disable-next-line import/no-webpack-loader-syntax
// require("script-loader!jsonlint");
import "codemirror/addon/lint/lint.css";
import "codemirror/addon/lint/lint";
import "codemirror/addon/lint/json-lint";

// 主题样式
import "../assets/theme-editor.css";
// 括号显示匹配
import "codemirror/addon/edit/matchbrackets";
// 高亮当前行
// import "codemirror/addon/selection/active-line";
// 括号、引号编辑和删除时成对出现
import "codemirror/addon/edit/closebrackets";
// 折叠代码要用到一些玩意
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/foldgutter";
import "codemirror/addon/fold/xml-fold";
import "codemirror/addon/fold/foldcode";
import "codemirror/addon/fold/brace-fold";
import "codemirror/addon/fold/indent-fold.js";
import "codemirror/addon/fold/markdown-fold.js";
import "codemirror/addon/fold/comment-fold.js";

// 搜索替换
import 'codemirror/addon/search/search.js';
import 'codemirror/addon/search/searchcursor.js';
import 'codemirror/addon/dialog/dialog.js';
import 'codemirror/addon/dialog/dialog.css';

import {useSystemStore} from "../store/index.js";
import {useFileStore} from "../store/fileStore.js";
import {mapState} from "pinia";
import {saveDataToFile} from "../utils/clientControl.js";

let currentEditor;

export default {
    name: "CodeMirror",
    components: {},
    data() {
        return {
            currentEditor: "",
        };
    },
    computed: {
        ...mapState(useSystemStore, ['insertImageAltText']),
        ...mapState(useFileStore, ['selectFileAddress'])
    },
    mounted() {
        this.init();

        this.$nextTick(() => {
            // 绑定 ctrl + s 快捷键保存文件
            document.addEventListener('keydown', (e) => {
                if (e.ctrlKey && e.key === 's') {
                    e.preventDefault();
                    this.handleSaveFile();
                }
            });
        })
    },
    methods: {
        init() {
            currentEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
                mode: "markdown",
                theme: "bluenote", // 主题样式
                lint: true,
                tabSize: 2,
                smartIndent: true, // 是否智能缩进
                styleActiveLine: true, // 当前行高亮
                lineNumbers: false, // 显示行号
                gutters: [],
                lineWrapping: true, // 自动换行
                matchBrackets: true, // 括号匹配显示
                autoCloseBrackets: true, // 输入和退格时成对
                foldGutter: true,
                highlightFormatting: true,
                codeFolding: true,
                styleActiveLineGutter: true
            });
            currentEditor.on('change', (cm, change) => {
                // 判断是否是内容变化（而不是 blur/事件触发）
                if (!change || !change.from || !change.to) {
                    return; // 非内容变化，直接返回
                }
                const editorValue = cm.getValue();
                this.$emit('editorChange', editorValue);
            });
            currentEditor.on('scroll', (cm) => {
                this.$emit('scroll', cm.getScrollInfo());
            })
        },

        /** 编辑器获取光标 */
        handleEditCursor() {
            currentEditor.focus();
        },

        /** 编辑器滚动方法 */
        handleScroll(scrollTop) {
            const cm = currentEditor;
            cm.scrollTo(0, scrollTop);
        },

        /*------------------------------------------------ 格式 -------------------------------------------------------*/
        /** 加粗方法 */
        handleApplyBold() {
            const cm = currentEditor;
            const selection = cm.getSelection();
            if (selection) {
                const start = cm.getCursor(true);  // 选区开始位置
                const end = cm.getCursor(false);   // 选区结束位置
                cm.replaceSelection(`**${selection}**`);
                const newCh = end.ch + 4;
                const newPos = {line: end.line, ch: newCh};
                cm.setCursor(newPos);
            } else {
                cm.replaceSelection('****');
                const cur = cm.getCursor();
                cm.setCursor({line: cur.line, ch: cur.ch - 2});
            }
            cm.focus();
        },
        /** 删除线 */
        handleApplyDel() {
            const cm = currentEditor;
            const selection = cm.getSelection();

            if (selection) {
                const start = cm.getCursor(true);
                const end = cm.getCursor(false);

                cm.replaceSelection(`~~${selection}~~`);
                const newCh = end.ch + 4; // 加上两个 ~~ 的长度
                const newPos = {line: end.line, ch: newCh};
                cm.setCursor(newPos);
            } else {
                cm.replaceSelection('~~~~');
                const cur = cm.getCursor();
                cm.setCursor({line: cur.line, ch: cur.ch - 2});
            }

            cm.focus();
        },

        /** 下划线 */
        handleApplyUnderline() {
            const cm = currentEditor;
            const selection = cm.getSelection();

            if (selection) {
                const start = cm.getCursor(true);
                const end = cm.getCursor(false);

                cm.replaceSelection(`<u>${selection}</u>`);
                const newCh = end.ch + 7;
                const newPos = {line: end.line, ch: newCh};
                cm.setCursor(newPos);
            } else {
                cm.replaceSelection('<u></u>');
                const cur = cm.getCursor();
                cm.setCursor({line: cur.line, ch: cur.ch - 7}); // 定位到 </u> 前面
            }

            cm.focus();
        },

        /** 倾斜 */
        handleApplyItalic() {
            const cm = currentEditor;
            const selection = cm.getSelection();

            if (selection) {
                const end = cm.getCursor(false);
                cm.replaceSelection(`*${selection}*`);
                const newCh = end.ch + 2; // 增加了一个 * 在前后
                const newPos = {line: end.line, ch: newCh};
                cm.setCursor(newPos);
            } else {
                cm.replaceSelection('**');
                const cur = cm.getCursor();
                cm.setCursor({line: cur.line, ch: cur.ch - 1}); // 定位在中间
            }

            cm.focus();
        },
        /** 代码块 */
        handleApplyCode() {
            // TODO 这里存在报错
            const cm = currentEditor;
            const selection = cm.getSelection();
            const curStart = cm.getCursor(true);
            const curEnd = cm.getCursor(false);

            if (selection) {
                const codeBlockContent = `\n\`\`\`\n${selection}\n\`\`\`\n`;
                cm.replaceSelection(codeBlockContent);
                cm.setCursor({
                    line: curStart.line + 1,
                    ch: 0
                });
            } else {
                const cursor = cm.getCursor();
                cm.replaceRange(
                    "```\n\n```",
                    {line: cursor.line, ch: 0},
                    {line: cursor.line, ch: 0}
                );
                cm.setCursor({line: cursor.line + 1, ch: 0});
            }
        },
        /** 行内标识 */
        handleApplyLineSign() {
            const cm = currentEditor;
            const selection = cm.getSelection();

            if (selection) {
                cm.replaceSelection(`\`${selection}\``);
                const end = cm.getCursor(false);
                const newPos = {line: end.line, ch: end.ch + 1};
                cm.setCursor(newPos);
            } else {
                cm.replaceSelection('``');
                const cur = cm.getCursor();
                cm.setCursor({line: cur.line, ch: cur.ch});
            }

            cm.focus();
        },
        /** 插入链接 */
        handleInsertLink() {
            const cm = currentEditor;
            const selection = cm.getSelection();
            const cursor = cm.getCursor();

            if (selection) {
                cm.replaceSelection(`[${selection}](https://example.com)`);
                const newCh = cursor.ch + selection.length + 2; // 定位到括号中间
                cm.setCursor({line: cursor.line, ch: newCh});
            } else {
                cm.replaceSelection('[文字](https://example.com)');
                cm.setCursor({line: cursor.line, ch: cursor.ch + 3}); // 定位到 "文" 后面
            }

            cm.focus();
        },
        /** 插入表格 */
        handleInsertTable() {
            const cm = currentEditor;
            const cursor = cm.getCursor();
            const table = `| 表头1 | 表头2 |\n|-------|-------|\n| 内容A | 内容B |\n`;
            cm.replaceRange(table, cursor, cursor);
            cm.setCursor({line: cursor.line + 1, ch: 0});
            cm.focus();
        },
        /** 插入图片 */
        handleInsertImage(url) {
            const cm = currentEditor;
            const cursor = cm.getCursor();
            const markdownImage = `\n![](${url})\n`;
            cm.replaceSelection(markdownImage);
            cm.setCursor({line: cursor.line + 1, ch: 0});
            // 在图片后插入注释文字
            if (this.insertImageAltText !== '') {
                const commentText = `${this.insertImageAltText}\n`;
                const newCursorPos = {line: cursor.line + 2, ch: 0};
                cm.replaceRange(commentText, newCursorPos, newCursorPos);
                cm.setCursor({line: cursor.line + 3, ch: 0});
            }
            cm.focus();
        },
        /** 有序列表 */
        handleInsertOrderedList() {
            const cm = currentEditor;
            const cursor = cm.getCursor();
            cm.replaceRange('1. ', cursor, cursor);
            cm.setCursor({line: cursor.line + 1, ch: 3});
            cm.focus();
        },
        /** 无序列表 */
        handleInsertUnorderedList() {
            const cm = currentEditor;
            const cursor = cm.getCursor();
            cm.replaceRange('- ', cursor, cursor);
            cm.setCursor({line: cursor.line + 1, ch: 2});
            cm.focus();
        },
        /** 标题 */
        handleInsertHeading(level) {
            const prefix = '#'.repeat(level) + ' ';
            const cm = currentEditor;
            const selection = cm.getSelection();
            const cursor = cm.getCursor();

            if (selection) {
                cm.replaceSelection(`\n${prefix}${selection}\n`);
                cm.setCursor({line: cursor.line + 1, ch: 0});
            } else {
                cm.replaceRange(`${prefix}标题\n`, cursor, cursor);
                cm.setCursor({line: cursor.line + 1, ch: 0});
            }

            cm.focus();
        },
        /** 插入文章尾方法 */
        handleInsertDownFooter(text) {
            const cm = currentEditor;
            const cursor = cm.getCursor();
            cm.replaceRange('\n' + text, cursor, cursor);
            cm.setCursor({line: cursor.line + 1, ch: 0});
            cm.focus();
        },

        /*------------------------------------------------ 功能 -------------------------------------------------------*/
        /** 保存方法 */
        handleSaveFile() {
            const cm = currentEditor;
            saveDataToFile(cm.getValue(), this.selectFileAddress);
        },

        /** 插入文本方法 */
        handleSetValue(val) {
            const cm = currentEditor;
            if (cm) {
                cm.setValue(val);
            }
            cm.focus();
        },

        /** 重置方法 */
        handleReset() {
            const cm = currentEditor;
            if (cm) {
                cm.setValue('');
            }
            cm.focus();
        },

        /** 查询 - 上一个方法 */
        handleFindPrev({searchText, caseSensitive}) {
            const cm = currentEditor;
            const doc = cm.getDoc();
            const cursor = doc.getSearchCursor(searchText, null, {
                caseFold: !caseSensitive,
                reverse: true
            });
            if (cursor.findNext()) {
                doc.setSelection(cursor.from(), cursor.to());
                cm.scrollIntoView(cursor.from(), 20);
            } else {
                console.log('未找到匹配项');
            }
        },

        /** 查询 - 下一个方法 */
        handleFindNext({searchText, caseSensitive}) {
            const cm = currentEditor;
            const doc = cm.getDoc();
            const cursor = doc.getSearchCursor(searchText, cm.getCursor(), {
                caseFold: !caseSensitive
            });
            if (cursor.findNext()) {
                doc.setSelection(cursor.from(), cursor.to());
                cm.scrollIntoView(cursor.from(), 20);
            } else {
                console.log('未找到匹配项');
            }
        },

        /** 查询 - 替换方法 */
        handleReplace({searchText, replaceText, caseSensitive}) {
            const cm = currentEditor;
            if (!cm || !searchText) return;

            const doc = cm.getDoc();
            const cursor = doc.getSearchCursor(searchText, doc.getCursor(), {
                caseFold: !caseSensitive,
            });

            if (cursor.findNext()) {
                doc.replaceRange(replaceText, cursor.from(), cursor.to());
            }
        },

        /** 查询 - 替换全部方法 */
        handleReplaceAll({searchText, replaceText, caseSensitive}) {
            const cm = currentEditor;
            if (!cm || !searchText) return;

            const doc = cm.getDoc();
            const text = doc.getValue();
            const flags = caseSensitive ? 'g' : 'gi';
            const regex = new RegExp(searchText, flags);

            const newText = text.replace(regex, replaceText);
            doc.setValue(newText);
        },

        /** 刷新编辑器布局 - 用于处理容器尺寸变化 */
        refreshEditor() {
            if (currentEditor) {
                currentEditor.refresh();
            }
        }
    }
}
;
</script>

<style scoped>
.editor-container {
    height: 100%;
    position: relative;
}

/* 高度自适应 */
.editor-container ::v-deep(.CodeMirror) {
    height: 100%;
    box-sizing: border-box;
}

.editor-container ::v-deep(.CodeMirror-scroll) {
    height: 100%;
    overflow-y: auto;
    overflow-x: auto;
}

.CodeMirror-foldgutter-folded.CodeMirror-guttermarker-subtle {
    color: black !important;
    font-size: 14px;
}

.CodeMirror-foldgutter-open:after {
    color: black !important;
    font-size: 14px;
}

.editor-container .cm-string {
    color: coral !important;
}
</style>

